using Microsoft.Extensions.Logging;
using System.Text.Json;
using Uantek.Common.Cache;
using Uantek.Device.Communication.Models;

namespace Uantek.Device.Communication.Utilities
{
    /// <summary>
    /// Redis数据管理器接口
    /// </summary>
    public interface IRedisDataManager
    {
        /// <summary>
        /// 缓存设备数据
        /// </summary>
        /// <param name="deviceData">设备数据</param>
        /// <param name="expiration">过期时间</param>
        /// <returns>操作结果</returns>
        Task<bool> CacheDeviceDataAsync(DeviceDataModel deviceData, TimeSpan? expiration = null);

        /// <summary>
        /// 获取设备数据
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <param name="timestamp">时间戳</param>
        /// <returns>设备数据</returns>
        Task<DeviceDataModel?> GetDeviceDataAsync(string deviceId, DateTime? timestamp = null);

        /// <summary>
        /// 获取设备历史数据
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <param name="startTime">开始时间</param>
        /// <param name="endTime">结束时间</param>
        /// <param name="limit">数量限制</param>
        /// <returns>设备数据列表</returns>
        Task<IEnumerable<DeviceDataModel>> GetDeviceHistoryAsync(string deviceId, DateTime startTime, DateTime endTime, int limit = 1000);

        /// <summary>
        /// 缓存设备状态
        /// </summary>
        /// <param name="deviceStatus">设备状态</param>
        /// <param name="expiration">过期时间</param>
        /// <returns>操作结果</returns>
        Task<bool> CacheDeviceStatusAsync(DeviceStatus deviceStatus, TimeSpan? expiration = null);

        /// <summary>
        /// 获取设备状态
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <returns>设备状态</returns>
        Task<DeviceStatus?> GetDeviceStatusAsync(string deviceId);

        /// <summary>
        /// 批量缓存设备数据
        /// </summary>
        /// <param name="deviceDataList">设备数据列表</param>
        /// <param name="expiration">过期时间</param>
        /// <returns>操作结果</returns>
        Task<int> BatchCacheDeviceDataAsync(IEnumerable<DeviceDataModel> deviceDataList, TimeSpan? expiration = null);

        /// <summary>
        /// 删除设备数据
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <param name="timestamp">时间戳（可选）</param>
        /// <returns>删除数量</returns>
        Task<int> DeleteDeviceDataAsync(string deviceId, DateTime? timestamp = null);

        /// <summary>
        /// 清理过期数据
        /// </summary>
        /// <param name="cutoffTime">截止时间</param>
        /// <returns>清理数量</returns>
        Task<int> CleanupExpiredDataAsync(DateTime cutoffTime);

        /// <summary>
        /// 获取设备数据统计信息
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <returns>统计信息</returns>
        Task<DeviceDataStatistics> GetDeviceDataStatisticsAsync(string deviceId);

        /// <summary>
        /// 设置设备配置
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <param name="config">配置数据</param>
        /// <returns>操作结果</returns>
        Task<bool> SetDeviceConfigAsync(string deviceId, Dictionary<string, object> config);

        /// <summary>
        /// 获取设备配置
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <returns>配置数据</returns>
        Task<Dictionary<string, object>?> GetDeviceConfigAsync(string deviceId);
    }

    /// <summary>
    /// Redis数据管理器实现
    /// </summary>
    public class RedisDataManager : IRedisDataManager
    {
        private readonly ILogger<RedisDataManager> _logger;
        private readonly string _keyPrefix;

        public RedisDataManager(ILogger<RedisDataManager> logger)
        {
            _logger = logger;
            _keyPrefix = "device_comm:";
        }

        public async Task<bool> CacheDeviceDataAsync(DeviceDataModel deviceData, TimeSpan? expiration = null)
        {
            try
            {
                var key = GenerateDataKey(deviceData.DeviceId, deviceData.Timestamp);
                var realtimeKey = GenerateRealtimeKey(deviceData.DeviceId);
                var dataJson = JsonSerializer.Serialize(deviceData, GetJsonOptions());

                var exp = expiration ?? TimeSpan.FromDays(30);

                // 缓存历史数据
                var historyResult = await Task.Run(() => RedisServer.Cache.Set(key, dataJson, exp));
                
                // 缓存实时数据
                var realtimeResult = await Task.Run(() => RedisServer.Cache.Set(realtimeKey, dataJson, TimeSpan.FromMinutes(10)));

                // 更新设备数据索引
                await UpdateDeviceIndexAsync(deviceData.DeviceId, deviceData.Timestamp);

                return historyResult && realtimeResult;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"缓存设备数据失败: {deviceData.DeviceId}");
                return false;
            }
        }

        public async Task<DeviceDataModel?> GetDeviceDataAsync(string deviceId, DateTime? timestamp = null)
        {
            try
            {
                string key;
                if (timestamp.HasValue)
                {
                    key = GenerateDataKey(deviceId, timestamp.Value);
                }
                else
                {
                    key = GenerateRealtimeKey(deviceId);
                }

                var dataJson = await Task.Run(() => RedisServer.Cache.Get(key));
                if (string.IsNullOrEmpty(dataJson))
                {
                    return null;
                }

                return JsonSerializer.Deserialize<DeviceDataModel>(dataJson, GetJsonOptions());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取设备数据失败: {deviceId}");
                return null;
            }
        }

        public async Task<IEnumerable<DeviceDataModel>> GetDeviceHistoryAsync(string deviceId, DateTime startTime, DateTime endTime, int limit = 1000)
        {
            try
            {
                var dataList = new List<DeviceDataModel>();
                var pattern = $"{_keyPrefix}data:{deviceId}:*";
                
                // 获取设备数据键
                var keys = await Task.Run(() => RedisServer.Cache.Keys(pattern));
                var sortedKeys = keys
                    .Where(key => IsKeyInTimeRange(key, startTime, endTime))
                    .OrderByDescending(key => ExtractTimestampFromKey(key))
                    .Take(limit)
                    .ToList();

                // 批量获取数据
                var pipeline = RedisServer.Cache.StartPipe();
                var tasks = new List<Task<string>>();
                
                foreach (var key in sortedKeys)
                {
                    tasks.Add(Task.Run(() => RedisServer.Cache.Get(key)));
                }

                await Task.Run(() => pipeline.EndPipe());
                var results = await Task.WhenAll(tasks);

                foreach (var dataJson in results)
                {
                    if (!string.IsNullOrEmpty(dataJson))
                    {
                        try
                        {
                            var deviceData = JsonSerializer.Deserialize<DeviceDataModel>(dataJson, GetJsonOptions());
                            if (deviceData != null && 
                                deviceData.Timestamp >= startTime && 
                                deviceData.Timestamp <= endTime)
                            {
                                dataList.Add(deviceData);
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.LogWarning(ex, "反序列化设备数据失败");
                        }
                    }
                }

                return dataList.OrderBy(d => d.Timestamp);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取设备历史数据失败: {deviceId}");
                return new List<DeviceDataModel>();
            }
        }

        public async Task<bool> CacheDeviceStatusAsync(DeviceStatus deviceStatus, TimeSpan? expiration = null)
        {
            try
            {
                var key = GenerateStatusKey(deviceStatus.DeviceId);
                var statusJson = JsonSerializer.Serialize(deviceStatus, GetJsonOptions());
                var exp = expiration ?? TimeSpan.FromHours(1);

                var result = await Task.Run(() => RedisServer.Cache.Set(key, statusJson, exp));
                
                // 更新设备状态变更时间
                var timestampKey = $"{_keyPrefix}status_timestamp:{deviceStatus.DeviceId}";
                await Task.Run(() => RedisServer.Cache.Set(timestampKey, DateTime.Now.Ticks.ToString(), exp));

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"缓存设备状态失败: {deviceStatus.DeviceId}");
                return false;
            }
        }

        public async Task<DeviceStatus?> GetDeviceStatusAsync(string deviceId)
        {
            try
            {
                var key = GenerateStatusKey(deviceId);
                var statusJson = await Task.Run(() => RedisServer.Cache.Get(key));

                if (string.IsNullOrEmpty(statusJson))
                {
                    return null;
                }

                return JsonSerializer.Deserialize<DeviceStatus>(statusJson, GetJsonOptions());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取设备状态失败: {deviceId}");
                return null;
            }
        }

        public async Task<int> BatchCacheDeviceDataAsync(IEnumerable<DeviceDataModel> deviceDataList, TimeSpan? expiration = null)
        {
            try
            {
                var pipeline = RedisServer.Cache.StartPipe();
                var exp = expiration ?? TimeSpan.FromDays(30);
                var count = 0;

                foreach (var deviceData in deviceDataList)
                {
                    try
                    {
                        var key = GenerateDataKey(deviceData.DeviceId, deviceData.Timestamp);
                        var dataJson = JsonSerializer.Serialize(deviceData, GetJsonOptions());
                        
                        pipeline.Set(key, dataJson, exp);
                        count++;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, $"准备批量缓存数据失败: {deviceData.DeviceId}");
                    }
                }

                await Task.Run(() => pipeline.EndPipe());
                return count;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量缓存设备数据失败");
                return 0;
            }
        }

        public async Task<int> DeleteDeviceDataAsync(string deviceId, DateTime? timestamp = null)
        {
            try
            {
                if (timestamp.HasValue)
                {
                    // 删除特定时间的数据
                    var key = GenerateDataKey(deviceId, timestamp.Value);
                    var result = await Task.Run(() => RedisServer.Cache.Del(key));
                    return (int)result;
                }
                else
                {
                    // 删除设备所有数据
                    var pattern = $"{_keyPrefix}data:{deviceId}:*";
                    var keys = await Task.Run(() => RedisServer.Cache.Keys(pattern));
                    
                    if (keys.Length > 0)
                    {
                        var result = await Task.Run(() => RedisServer.Cache.Del(keys));
                        return (int)result;
                    }
                    return 0;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"删除设备数据失败: {deviceId}");
                return 0;
            }
        }

        public async Task<int> CleanupExpiredDataAsync(DateTime cutoffTime)
        {
            try
            {
                var pattern = $"{_keyPrefix}data:*";
                var keys = await Task.Run(() => RedisServer.Cache.Keys(pattern));
                var expiredKeys = new List<string>();

                foreach (var key in keys)
                {
                    var timestamp = ExtractTimestampFromKey(key);
                    if (timestamp.HasValue && timestamp.Value < cutoffTime)
                    {
                        expiredKeys.Add(key);
                    }
                }

                if (expiredKeys.Count > 0)
                {
                    var result = await Task.Run(() => RedisServer.Cache.Del(expiredKeys.ToArray()));
                    _logger.LogInformation($"清理过期数据完成，删除了 {result} 个数据项");
                    return (int)result;
                }

                return 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清理过期数据失败");
                return 0;
            }
        }

        public async Task<DeviceDataStatistics> GetDeviceDataStatisticsAsync(string deviceId)
        {
            try
            {
                var statistics = new DeviceDataStatistics { DeviceId = deviceId };
                var pattern = $"{_keyPrefix}data:{deviceId}:*";
                
                var keys = await Task.Run(() => RedisServer.Cache.Keys(pattern));
                statistics.TotalRecords = keys.Length;

                if (keys.Length > 0)
                {
                    var timestamps = keys
                        .Select(ExtractTimestampFromKey)
                        .Where(t => t.HasValue)
                        .Select(t => t.Value)
                        .OrderBy(t => t)
                        .ToList();

                    if (timestamps.Count > 0)
                    {
                        statistics.FirstRecordTime = timestamps.First();
                        statistics.LastRecordTime = timestamps.Last();
                        statistics.TimeSpan = statistics.LastRecordTime - statistics.FirstRecordTime;
                    }
                }

                // 获取实时数据
                var realtimeData = await GetDeviceDataAsync(deviceId);
                if (realtimeData != null)
                {
                    statistics.LastUpdateTime = realtimeData.Timestamp;
                    statistics.DataQuality = realtimeData.Quality;
                }

                return statistics;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取设备数据统计失败: {deviceId}");
                return new DeviceDataStatistics { DeviceId = deviceId };
            }
        }

        public async Task<bool> SetDeviceConfigAsync(string deviceId, Dictionary<string, object> config)
        {
            try
            {
                var key = GenerateConfigKey(deviceId);
                var configJson = JsonSerializer.Serialize(config, GetJsonOptions());
                
                var result = await Task.Run(() => RedisServer.Cache.Set(key, configJson, TimeSpan.FromDays(365)));
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"设置设备配置失败: {deviceId}");
                return false;
            }
        }

        public async Task<Dictionary<string, object>?> GetDeviceConfigAsync(string deviceId)
        {
            try
            {
                var key = GenerateConfigKey(deviceId);
                var configJson = await Task.Run(() => RedisServer.Cache.Get(key));

                if (string.IsNullOrEmpty(configJson))
                {
                    return null;
                }

                return JsonSerializer.Deserialize<Dictionary<string, object>>(configJson, GetJsonOptions());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取设备配置失败: {deviceId}");
                return null;
            }
        }

        private async Task UpdateDeviceIndexAsync(string deviceId, DateTime timestamp)
        {
            try
            {
                var indexKey = $"{_keyPrefix}index:{deviceId}";
                var timestampString = timestamp.ToString("yyyyMMddHHmmss");
                
                // 添加到有序集合，用于时间范围查询
                await Task.Run(() => RedisServer.Cache.ZAdd(indexKey, (timestamp.Ticks, timestampString)));
                
                // 设置索引过期时间
                await Task.Run(() => RedisServer.Cache.Expire(indexKey, TimeSpan.FromDays(31)));
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, $"更新设备索引失败: {deviceId}");
            }
        }

        private string GenerateDataKey(string deviceId, DateTime timestamp)
        {
            return $"{_keyPrefix}data:{deviceId}:{timestamp:yyyyMMddHHmmss}";
        }

        private string GenerateRealtimeKey(string deviceId)
        {
            return $"{_keyPrefix}realtime:{deviceId}";
        }

        private string GenerateStatusKey(string deviceId)
        {
            return $"{_keyPrefix}status:{deviceId}";
        }

        private string GenerateConfigKey(string deviceId)
        {
            return $"{_keyPrefix}config:{deviceId}";
        }

        private bool IsKeyInTimeRange(string key, DateTime startTime, DateTime endTime)
        {
            var timestamp = ExtractTimestampFromKey(key);
            return timestamp.HasValue && timestamp.Value >= startTime && timestamp.Value <= endTime;
        }

        private DateTime? ExtractTimestampFromKey(string key)
        {
            try
            {
                var parts = key.Split(':');
                if (parts.Length >= 3)
                {
                    var timestampString = parts[^1]; // 最后一部分
                    if (DateTime.TryParseExact(timestampString, "yyyyMMddHHmmss", 
                        System.Globalization.CultureInfo.InvariantCulture, 
                        System.Globalization.DateTimeStyles.None, out var timestamp))
                    {
                        return timestamp;
                    }
                }
                return null;
            }
            catch
            {
                return null;
            }
        }

        private JsonSerializerOptions GetJsonOptions()
        {
            return new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                WriteIndented = false,
                DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
            };
        }
    }

    /// <summary>
    /// 设备数据统计信息
    /// </summary>
    public class DeviceDataStatistics
    {
        /// <summary>
        /// 设备ID
        /// </summary>
        public string DeviceId { get; set; } = string.Empty;

        /// <summary>
        /// 总记录数
        /// </summary>
        public int TotalRecords { get; set; }

        /// <summary>
        /// 第一条记录时间
        /// </summary>
        public DateTime? FirstRecordTime { get; set; }

        /// <summary>
        /// 最后一条记录时间
        /// </summary>
        public DateTime? LastRecordTime { get; set; }

        /// <summary>
        /// 最后更新时间
        /// </summary>
        public DateTime? LastUpdateTime { get; set; }

        /// <summary>
        /// 时间跨度
        /// </summary>
        public TimeSpan? TimeSpan { get; set; }

        /// <summary>
        /// 数据质量
        /// </summary>
        public int DataQuality { get; set; }
    }
}